/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#include "pch.h"
#include <journal/common/settings_service_impl.hpp>

namespace journal {

namespace b = baja;
namespace s = baja::storage;

// TRACK: bug 363 : need to have var_console make changes through settings
//                 this function is only needed to support the saving of all
//                 groups at once.
std::wstring settings_service::groupFullName(const std::wstring& path, const std::wstring& name)
{
    std::wstring fullName;
    if (path.size() != 0)
    {
        fullName = path + L"\\" + name;
    }
    else
    {
        fullName = name;
    }
    return fullName;
}

// TRACK: bug 363 : need to have var_console make changes through settings
//                 this function is only needed to support the saving of all
//                 groups at once.
void settings_service::saveGroup(const std::wstring& fullName, const std::shared_ptr<journal::setting_group>& group)
{
    if (group->settingCount() == 0)
    {
        return;
    }

    size_t settingCount = group->settingCount();
    for (size_t i = 0 ; i < settingCount ; ++i)
    {
        std::shared_ptr<journal::setting_base> setting = group->setting(static_cast<int>(i));
        std::wstring settingFullName = fullName + L"\\" + setting->name();
        s::binary_blob valueBlob(setting->getValueBufferSize(), setting->getValueBuffer());
        _settingGroupTable->write(settingFullName, valueBlob);
    }
}

// TRACK: bug 363 : need to have var_console make changes through settings
//                 this function is only needed to support the saving of all
//                 groups at once.
void settings_service::saveGroupTree(const std::wstring& path, std::shared_ptr<journal::setting_group> group)
{
    std::wstring fullName = groupFullName(path, group->name());

    // save self
    saveGroup(fullName, group);

    // save children
    size_t groupCount = group->childrenCount();
    for (size_t i = 0 ; i < groupCount ; ++i)
    {
        saveGroupTree(fullName, group->child(static_cast<int>(i)));
    }
}

// TRACK: bug 363 : need to have var_console make changes through settings
//                 this function is only needed to support the saving of all
//                 groups at once.
void settings_service::save()
{
    size_t groupCount = _rootGroup->childrenCount();
    for (size_t i = 0 ; i < groupCount ; ++i)
    {
        saveGroupTree(L"", _rootGroup->child(static_cast<int>(i)));
    }
}

void settings_service::saveSetting(const b::wchar* fullName, std::shared_ptr<journal::isetting_base> setting)
{
    s::binary_blob valueBlob(setting->getValueBufferSize(), setting->getValueBuffer());
    _settingGroupTable->write(fullName, valueBlob);
}

void settings_service::load()
{
    std::map<std::wstring, s::binary_blob> result;
    _settingGroupTable->readAll(result);

    for (auto &iter : result)
    {
        std::shared_ptr<isetting_base> setting = this->findSetting(iter.first.c_str());
        if (setting == nullptr)
        {
            continue;
        }
        memcpy(
            setting->getValueBuffer(),
            iter.second._buffer,
            setting->getValueBufferSize());
    }
}

void settings_service::resetGroup(const std::wstring& fullName, const std::shared_ptr<journal::setting_group>& group)
{
    if (group->settingCount() == 0)
    {
        return;
    }

    size_t settingCount = group->settingCount();
    for (size_t i = 0 ; i < settingCount ; ++i)
    {
        std::shared_ptr<journal::setting_base> setting = group->setting(static_cast<int>(i));
        setting->reset();
    }
}

void settings_service::resetGroupTree(const std::wstring& path, std::shared_ptr<journal::setting_group> group)
{
    std::wstring fullName = groupFullName(path, group->name());

    // save self
    resetGroup(fullName, group);

    // save children
    size_t groupCount = group->childrenCount();
    for (size_t i = 0 ; i < groupCount ; ++i)
    {
        resetGroupTree(fullName, group->child(static_cast<int>(i)));
    }
}

void settings_service::reset()
{
    size_t groupCount = _rootGroup->childrenCount();
    for (size_t i = 0 ; i < groupCount ; ++i)
    {
        resetGroupTree(L"", _rootGroup->child(static_cast<int>(i)));
    }
    _settingGroupTable->common()->disposeAll();
}

} // journal